package BNS.wheat;

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.*;
import BNS.graphs.*;

/** Used by MarketPanel to display buying and selling prices of each neighbour. 
	TODO: make class internal to MarketPanel?
	*/
public class PricesChart {
	
//	private NodeState[] nodeStates;	
//	protected Graph graph;
	private int chartL, chartR, chartT, chartB, chartW, chartH;
	private int plotL, plotR, plotT, plotB, plotW, plotH;
	private boolean supplier;
	private static final Color background= new Color(230,230,180);
	protected NbrBox[] nbrBox;
	private static int boxWidth, colWidth;
	
	/** Initializes variables needed to draw a PricesChart.
		@param lf number of pixels to left side
		@param tp number of pixels to top side
		@param wd number of pixels wide
		@param ht number of pixels height
		@param sup true iff a supplier, false iff consumer
		@param graph the Graph defining the local neighbourhood
		*/
	public PricesChart(int lf, int tp, int wd, int ht, boolean sup, Graph graph) { 
		chartL=lf;  chartT=tp;  chartW= wd;  chartH= ht;
		chartR= chartL+chartW;  chartB= chartT+chartH;
		plotL= chartL+60;	// for labels "price", "volume", "best"
		plotB= chartB-25;	// for values of "quantity"
		plotT= chartT+20;	// for node labels
//		plotT= chartT;		// for no node labels
		plotR= chartR;  plotH=plotB-plotT;  plotW=plotR-plotL;
		//System.err.format("PricesChart constructor %d %d %d %d %d %d%n",
		//				  chartL,chartT,chartW,chartH,  chartR,chartB); 
		supplier= sup;
		nbrBox= new NbrBox[graph.numNodes()-1];
		boxWidth= plotW/nbrBox.length;
		colWidth= 60;	if (colWidth>boxWidth-6) colWidth= boxWidth-6;
		Enumeration eno= graph.enumNodes();
		eno.nextElement();	// throw away the first node... it's the eigenNode.
		for (int i=0; i<nbrBox.length; i++) {
			Node node= (Node)eno.nextElement();
			nbrBox[i]= new NbrBox(//node.lbl+
								  "+"+node.otherEdges,
								  plotL+i*boxWidth+boxWidth/2);
			}
		}
	
	class NbrBox {
		String text;
		int center;
		public NbrBox(String t, int c) { text=t; center=c; }
		public void show(Graphics g, NodeState ns) {
			g.setColor(background);
			g.fillRect(center-colWidth/2,plotT, colWidth,plotH);
			g.setColor(Color.black);
			plotString(g, center, plotT-2, text);		// column title (if used)
			if (ns.sellingVolume > 0) {
				plotString(g, center, plotB+14, form(ns.sellingVolume));
				//plotString(g, center, plotB+28, form(ns.sellingPrice));
				int v= vert(ns.sellingPrice);
				plotString(g, center, v-2, form(ns.sellingPrice));
				g.drawLine(center-colWidth/2,v, center+colWidth/2,v);
				}
			if (ns.bestPrice < Float.MAX_VALUE) {
				//plotString(g, center, plotB+42, form(1/ns.bestPrice));
				int v= vert(1/ns.bestPrice);
				g.drawOval(center-3,v-3,6,6);
				}
			}
		}
	
	private void plotString(Graphics g, int center, int vert, String text) {
		FontMetrics fontmetrics= g.getFontMetrics();
		//halfChar= fontmetrics.getAscent()/2;
		int halfWide= fontmetrics.stringWidth(text)/2;
		g.drawString(text, center-halfWide, vert);
		}
	
	/** TODO: make private */
	public static String form(double x) { 
		String s= String.format("%.3g",x); 
		if (s.startsWith("0")) s= s.substring(1);
		if (s.endsWith("0")) s= s.substring(0,s.length()-1);
		return s;
		}
	
	/** Paint the data for every neighbour.
		Called by MarketPanel. 
		TODO: make protected?
		*/
	public void paint(Graphics g, NodeState[] nodeStates) {
		g.setColor(Color.white);
		//g.fillRect(plotL,plotT,plotW,plotH);
		
		g.setColor(Color.black);
		g.drawString("quantity:",	chartL,plotB+14);
//		g.drawString("    price",	chartL,plotB+28);
//		g.drawString("    offer",	chartL,plotB+42);
		
		//System.err.println("drawBars...");
		g.setColor(Color.black);
		for (int i=1; i<nodeStates.length; i++) 
			nbrBox[i-1].show(g,nodeStates[i]);
		
		if (nodeStates[0].sellingVolume > 0) { 
			int pBar= vert(1/nodeStates[0].sellingPrice);
			//System.err.println("myPrice "+nodeStates[0].sellingPrice+"  pBar"+pBar);
			g.setColor(Color.red);
			g.drawLine(chartL,pBar,plotR,pBar);
			plotString(g, (plotL+chartL)/2, pBar-2, form(1/nodeStates[0].sellingPrice));
			}
		}
	
	/** converts a (positive!) price to a position using a non-linear map. 
		The "central" value of the map is 1.0; values near it are spread out, 
		values far away are progressively less distinguishable.
		The distance between p and 2p is the same as between 1/p and 1/(2p).
		*/
	public double priceQuad(double x) { 
		double quad= Math.atan(x)*2/Math.PI;
		return supplier? quad : 1.-quad;
		}
	
	private int vert(double x) { return plotB- (int)(priceQuad(x)*(plotH)); }
		
	}
